package map.tile.server.util;

import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.BCUtil;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class SM2Example {
    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    public static String encrypt(String originText, PublicKey publicKey) throws Exception {
        byte[] plaintext= originText.getBytes(StandardCharsets.UTF_8);
        Cipher cipher = Cipher.getInstance("SM2", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return new BASE64Encoder().encodeBuffer(cipher.doFinal(plaintext));
    }


    public static  byte[] encrypt( byte[] plaintext, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("SM2", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(plaintext);
    }
    public static byte[]  encrypt2(String originText, PublicKey publicKey) throws Exception {
        byte[] plaintext=originText.getBytes(StandardCharsets.UTF_8);
        Cipher cipher = Cipher.getInstance("SM2", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(plaintext);
    }
    public static String decrypt(String encryptedText , PrivateKey privateKey) throws Exception {
        byte[] cipherText=new BASE64Decoder().decodeBuffer(encryptedText);
        Cipher cipher = Cipher.getInstance("SM2", "BC");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return new String(cipher.doFinal(cipherText),StandardCharsets.UTF_8);
    }

    public static String decrypt2(byte[] cipherText, PrivateKey privateKey) throws Exception {

        Cipher cipher = Cipher.getInstance("SM2", "BC");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return new String(cipher.doFinal(cipherText),StandardCharsets.UTF_8);
    }
    public static PublicKey generateSM2PublicKey(String publicKeyStr) throws Exception {
        // 解析 Base64 编码的字符串
        byte[] keyBytes = Base64.getDecoder().decode(publicKeyStr);

        // 创建 X509EncodedKeySpec 对象
        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);

        // 使用 KeyFactory 生成 PublicKey
        KeyFactory kf = KeyFactory.getInstance("EC"); // SM2 使用 EC 算法
        PublicKey publicKey = kf.generatePublic(spec);

        return publicKey;
    }
    public static PrivateKey generateSM2PrivateKey(String publicKeyStr) throws Exception {
        // 解析 Base64 编码的字符串
        byte[] keyBytes = Base64.getDecoder().decode(publicKeyStr);

        // 创建 X509EncodedKeySpec 对象
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);

        // 使用 KeyFactory 生成 PublicKey
        KeyFactory kf = KeyFactory.getInstance("EC"); // SM2 使用 EC 算法
        PrivateKey privateKey =  kf.generatePrivate(spec);

        return privateKey;
    }


    public static void main(String[] args) throws Exception {
//        String publicKeyStr ="MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEqUT+QVONldXjsafu/Hk88tOdCHWX13/EtfYKfbIFAKesp4bpM+fk65nqiBS2la8DG70eTQS8hmwirWQ+Jc1oLw==";
//
//        String privateKeyStr ="MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg1ORCRrVXHOJv6Q1QZnc8fHdWul0Rst3vLs5sBaOXR4OgCgYIKoEcz1UBgi2hRANCAASpRP5BU42V1eOxp+78eTzy050IdZfXf8S19gp9sgUAp6ynhukz5+TrmeqIFLaVrwMbvR5NBLyGbCKtZD4lzWgv";
//        PublicKey publicKey = generateSM2PublicKey(publicKeyStr);
//        PrivateKey privateKey = generateSM2PrivateKey(privateKeyStr);
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");
        keyPairGenerator.initialize(new ECGenParameterSpec("sm2p256v1"));

        // 生成密钥对
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        // 获取公钥和私钥
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();

        String privateKeyStr= HexUtil.encodeHexStr(privateKey.getEncoded());
        String publicKeyStr=HexUtil.encodeHexStr(publicKey.getEncoded());
        System.out.println("后端privateKey=>" + privateKeyStr);
        System.out.println("后端publicKey=>" + publicKeyStr);

        String publicKeyQ = HexUtil.encodeHexStr(((BCECPublicKey) publicKey).getQ().getEncoded(false));
        System.out.println("web前端使用公钥Q:"+ publicKeyQ);
        // 生成私钥 D，以D值做为js端的解密私钥
        String privateKeyD = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(privateKey));
        System.out.println("web前端使用私钥D:"+ privateKeyD);
        // 使用BouncyCastle库，初始化SM2密钥生成器


        // 明文
        String plaintext = "Hello, SM2!";

////        // 使用公钥加密明文
//        String encryptedText=encrypt(plaintext,publicKey);
//        System.out.println("-----");
//        System.out.println(encryptedText);
////        // 使用私钥解密密文
//        String resultText = decrypt(encryptedText, privateKey);
//        System.out.println(resultText);

//        generatePublicAndPrivateKey();
        String temp=SM2Util.encrypt(plaintext,privateKeyStr,publicKeyStr);
        System.out.println("-----");
        System.out.println(temp);
//        temp=temp.substring(2);
        temp=SM2Util.decrypt(temp,privateKeyStr,publicKeyStr);
        System.out.println("-----");
        System.out.println(temp);




    }


    public static void generatePublicAndPrivateKey() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
//        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");
//        keyPairGenerator.initialize(new ECGenParameterSpec("sm2p256v1"));
//
//        // 生成密钥对
//        KeyPair keyPair = keyPairGenerator.generateKeyPair();
//        // 获取公钥和私钥
//        PublicKey publicKey = keyPair.getPublic();
//        PrivateKey privateKey = keyPair.getPrivate();
//        System.out.println(publicKey.getAlgorithm());
//        System.out.println(publicKey.getFormat());
//        System.out.println("公钥");
//        System.out.println(Base64.getEncoder().encodeToString(publicKey.getEncoded()));
//        System.out.println("私钥");
//        System.out.println(Base64.getEncoder().encodeToString(privateKey.getEncoded()));



        String text = "我是一段测试aaaa";
        // 生成密钥对

        // 服务器端使用
//        // 生成私钥
//        String privateKey = HexUtil.encodeHexStr(keyPair.getPrivate().getEncoded());
//        // 生成公钥
//        String publicKey = HexUtil.encodeHexStr(keyPair.getPublic().getEncoded());
//        System.out.println("privateKey=>" + privateKey);
//        System.out.println("publicKey=>" + publicKey);
//
//        // 前端使用
//        // 生成公钥 Q，以Q值做为js端的加密公钥
//        String publicKeyQ = HexUtil.encodeHexStr(((BCECPublicKey) keyPair.getPublic()).getQ().getEncoded(false));
//        System.out.println("公钥Q:"+ publicKeyQ);
//        // 生成私钥 D，以D值做为js端的解密私钥
//        String privateKeyD = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(keyPair.getPrivate()));
//        System.out.println("私钥D:"+ privateKeyD);
//
//        // 服务端加解密
//
//        System.out.println("encodeStr=>" + encodeStr);
//        System.out.println("formatStr=>" + formatStr);

    }
}